#include "../include/dexgel/rendererdx.hpp"
#include "../include/dexgel/texturedx.hpp"
#include "../include/dexgel/meshdx.hpp"


using namespace dexgel;
using namespace dexgel::priv;

// Declare our static variables
IDirect3D9* RendererDx::mInterface = NULL;
IDirect3DDevice9* RendererDx::mDevice = NULL;
ID3DXEffect*      RendererDx::mEffect = NULL;       // D3DX effect interface
HRESULT RendererDx::mResult = 0;

int RendererDx::mMaxLights = 0; // Maximum number of lights for the current display adapter
D3DLIGHT9* RendererDx::mLights = NULL; // Array of possible lights 

/////////////
// Macros //
///////////

// Gets the A, R, G, and B from an D3DCOLOR
#define GET_A(c) ((c >> 24) & 0xFF)
#define GET_R(c) ((c >> 16) & 0xFF)
#define GET_G(c) ((c >> 8) & 0xFF)
#define GET_B(c) (c & 0xFF)

#define DEG2RAD(x) (x * (D3DX_PI / 180.0f)) // Converts degrees to radians
#define RAD2DEG(x) (x * (180.0f / D3DX_PI)) // Converts radians to degrees

void RendererDx::initShaders()
{
	// Define DEBUG_VS and/or DEBUG_PS to debug vertex and/or pixel shaders with the 
	// shader debugger. Debugging vertex shaders requires either REF or software vertex 
	// processing, and debugging pixel shaders requires REF.  The 
	// D3DXSHADER_FORCE_*_SOFTWARE_NOOPT flag improves the debug experience in the 
	// shader debugger.  It enables source level debugging, prevents instruction 
	// reordering, prevents dead code elimination, and forces the compiler to compile 
	// against the next higher available software target, which ensures that the 
	// unoptimized shaders do not exceed the shader model limitations.  Setting these 
	// flags will cause slower rendering since the shaders will be unoptimized and 
	// forced into software.  See the DirectX documentation for more information about 
	// using the shader debugger.
	DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE;

#if defined( DEBUG ) || defined( _DEBUG )
	// Set the D3DXSHADER_DEBUG flag to embed debug information in the shaders.
	// Setting this flag improves the shader debugging experience, but still allows 
	// the shaders to be optimized and to run exactly the way they will run in 
	// the release configuration of this program.
	dwShaderFlags |= D3DXSHADER_DEBUG;
#endif

#ifdef DEBUG_VS
	dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
#endif
#ifdef DEBUG_PS
	dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
#endif

	// Preshaders are parts of the shader that the effect system pulls out of the 
	// shader and runs on the host CPU. They should be used if you are GPU limited. 
	// The D3DXSHADER_NO_PRESHADER flag disables preshaders.
	dwShaderFlags |= D3DXSHADER_NO_PRESHADER;

	// If this fails, there should be debug output as to 
	// why the .fx file failed to compile
	HRESULT mResult = D3DXCreateEffectFromFile( mDevice, "effect.fx", NULL, NULL, dwShaderFlags, NULL, &mEffect, NULL );
	assert(mResult == D3D_OK);
}


// Initializes our D3D object -- Returns true on success, false otherwise
bool RendererDx::init(HWND hwnd)
{
	// Create the D3D object, which is needed to create the D3DDevice.
	mInterface = Direct3DCreate9(D3D_SDK_VERSION);

	// Error Check
	if(mInterface == NULL)
		return false;

	D3DPRESENT_PARAMETERS params = {0}; 
	params.Windowed = TRUE; 
	params.BackBufferCount = 1;
	params.SwapEffect = D3DSWAPEFFECT_FLIP;
	params.BackBufferFormat = D3DFMT_UNKNOWN;
	params.EnableAutoDepthStencil = true;
	params.AutoDepthStencilFormat = D3DFMT_D24S8;  //D3DFMT_D24S8 D3DFMT_D16
	

	mResult = mInterface->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
									   D3DCREATE_HARDWARE_VERTEXPROCESSING,
									   &params, &mDevice);

	// It's possible we'll get an error because not all vid-cards can handle vertex processing
	// So in the event we do get an error we'll try to make the device again.  We will
	// only change D3DCREATE_HARDWARE_VERTEXPROCESSING to D3DCREATE_SOFTWARE_VERTEXPROCESSING
	// which says, "Do the vertex processing in software" 
	if(mResult != D3D_OK)
	{
		mResult = mInterface->CreateDevice(D3DADAPTER_DEFAULT,
										   D3DDEVTYPE_HAL,
										   hwnd,
										   D3DCREATE_SOFTWARE_VERTEXPROCESSING,
										   &params,
										   &mDevice);
		if(mResult != D3D_OK)
			return false; // Couldn't create a D3D 9.0 device
	}

	//Turn off back face culling so our geometry is always visible
	mResult = mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); //D3DCULL_NONE
	assert(mResult == D3D_OK);

	// Turn off D3D lighting, since we are providing our own vertex colors
	mResult = mDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
	assert(mResult == D3D_OK);

	// Turn on Z-buffering
	mResult = mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);

	initLights();

	initShaders();



    return true; // We got loaded
}

// Free up all the memory
void RendererDx::deinit()
{
	if(mDevice != NULL)
		mDevice->Release();

	if(mInterface != NULL)
		mInterface->Release();

	// Zero out our D3D interface and device 
	mDevice = NULL;
	mInterface = NULL;
}


// Begins the scene
void RendererDx::begin()
{
	// This begins our scene.
	assert( 
			SUCCEEDED( mDevice->BeginScene() )
			);

}

// End the scene and draw it
void RendererDx::end()
{
	// This ends the scene
	assert( SUCCEEDED(
		 mDevice->EndScene() 
		 ));

	// This presents (draws) the next back buffer (we only have one in our case) to the screen
	// By parameter:
	// NULL -- Must be NULL unless a swap chain was created with D3DSWAPEFFECT_COPY
	//		   **NOTE** We used D3DSWAPEFFECT_DISCARD
	// NULL -- Must be NULL unless a swap chain was created with D3DSWAPEFFECT_COPY
	// NULL -- HWND whose client area is taken as the target for this presentation.  If this is
	//		   NULL then the HWND set in the D3DPRESENT_PARAMETERS (set in our init() function)
	//		   is used
	// NULL -- Must be NULL unless a swap chain was created with D3DSWAPEFFECT_COPY 
	assert(  SUCCEEDED(
		mDevice->Present(NULL, NULL, NULL, NULL)
		));
}

// This renders a list of SVertex type vertices that is "numVerts" long
bool RendererDx::render(SVertex *vertList, int numTris)
{
	// The first thing we have to do before rendering is tell D3D what
	// type of vertices we'll be rendering.  We do this by passing the
	// #define that stipulates our vertex type.
	mDevice->SetFVF(SVertexType);
	
	// Now we are ready to render.  We can do this with one function call.
	// You'll notice the "UP" in the function name.  This stands for "user pointer" and 
	// means that we are passing D3D a pointer to a list of vertices to be rendered.  
	// Optionally we could use a D3D vertex buffer, this is a more specialized class that
	// increases rendering speeds.

	assert(  SUCCEEDED(
		mResult = mDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, numTris, vertList, sizeof(SVertex))
	));
	
	return (mResult == D3D_OK); // Returns status of DrawPrimitiveUP()
}

bool RendererDx::render( LitVertex *vertList, int numTris )
{
	// Set the flexible vertex format
	mDevice->SetFVF(LitVertexType);

	assert(  SUCCEEDED(
		mResult = mDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, numTris, vertList, sizeof(LitVertex))
		));

	return (mResult == D3D_OK); // Returns status of DrawPrimitiveUP()
}

bool RendererDx::render( VertexUV *vertList, int numTris )
{
	// Set the flexible vertex format
	mDevice->SetFVF(VertexTypeUV);

	assert(  SUCCEEDED(
		mResult = mDevice->DrawPrimitiveUP(D3DPT_TRIANGLELIST, numTris, vertList, sizeof(VertexUV))
		));

	return (mResult == D3D_OK); // Returns status of DrawPrimitiveUP()
}



bool RendererDx::renderLine( SVertex *gVertPool, int numVerts )
{
	mDevice->SetFVF(SVertexType);
	assert(  SUCCEEDED(
		mResult = mDevice->DrawPrimitiveUP(D3DPT_LINELIST, numVerts/2, gVertPool, sizeof(SVertex))
		));

	return (mResult == D3D_OK); // Returns status of DrawPrimitiveUP()
}


bool RendererDx::render(SVertex *vertList, int numVerts, unsigned short *indexList, int numIndices)
{
	// Set the flexible vertex format
	mDevice->SetFVF(SVertexType);

	// This is the D3D function that takes vertex arrays and index arrays
	// and renders them to the screen.  
	// By parameter:
	// D3DPT_TRIANGLELIST -- The type of primitive to render
	// 0 -- Lowest numbered index into the vertex array
	// numVerts -- Number of vertices in the vertex array
	// numIndices / 3 -- Number of primitives (in our case triangles) to render
	// indexList -- Pointer to index array
	// D3DFMT_INDEX16 -- Data format of the index array (a WORD is 16-bit)
	// vertList -- Point to the vertex array
	// sizeof(SVertex) -- Size of an individual vertex
	mResult = mDevice->DrawIndexedPrimitiveUP(D3DPT_TRIANGLELIST, 0, numVerts, numIndices / 3,
		indexList, D3DFMT_INDEX16, vertList, sizeof(SVertex));
	return (mResult == D3D_OK);
}





// Clears the viewport to a specified ARGB color
bool RendererDx::clearColor(int color, float zDepth)
{
	//mResult = mDevice->Clear(0, NULL, D3DCLEAR_TARGET, color, 1.0f, 0);
	//	return (mResult == D3D_OK);

	// Clear the color and z-depth
	mResult = mDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, color, zDepth, 0);
	return (mResult == D3D_OK);
}


void RendererDx::SetTransform( float* matWorld )
{
	D3DXMATRIXA16 *m = (D3DXMATRIXA16*)matWorld;
	mResult = mDevice->SetTransform( D3DTS_WORLD, m );
	assert(mResult == D3D_OK);

	mWorld = glm::mat4(  (*m)[0],  (*m)[1],  (*m)[2],  (*m)[3],
						(*m)[4],  (*m)[5],  (*m)[6],  (*m)[7],
						(*m)[8],  (*m)[9],  (*m)[10],  (*m)[11],
						(*m)[12],  (*m)[13],  (*m)[14],  (*m)[15]
	);

}

void RendererDx::setViewMatrix( const glm::vec3 &eye, const glm::vec3 &lookAt )
{
	D3DXMATRIXA16 m;
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f); // World's up vector

	// Create and set the view matrix
	// **NOTE** We can cast to (D3DXVECTOR3*) because our CVector has it's data members (x,y,z)
	// declared the same way a D3DXVECTOR3 does
	D3DXMatrixLookAtLH(&m, (D3DXVECTOR3*)(&eye), (D3DXVECTOR3*)(&lookAt), &up);
	mDevice->SetTransform(D3DTS_VIEW, &m); // Set our view of the world


	mWorldView = glm::mat4(  
		m[0],  m[1],  m[2],  m[3],
		m[4],  m[5],  m[6],  m[7],
		m[8],  m[9],  m[10], m[11],
		m[12], m[13], m[14], m[15]
	);

}

void RendererDx::setViewMatrix(float* m)
{
	mWorldView = glm::mat4(  
		m[0],  m[1],  m[2],  m[3],
		m[4],  m[5],  m[6],  m[7],
		m[8],  m[9],  m[10], m[11],
		m[12], m[13], m[14], m[15]
	);
	mDevice->SetTransform(D3DTS_VIEW, reinterpret_cast<D3DXMATRIXA16*>(m) );
}


void RendererDx::setProjMatrix(float fov, float aspectRatio, float nearClip, float farClip)
{
	D3DXMATRIXA16 m;

	// Create and set projection matrix
	D3DXMatrixPerspectiveFovLH(&m, fov, aspectRatio, nearClip, farClip);
	mDevice->SetTransform(D3DTS_PROJECTION, &m);

	mProjection = glm::mat4(  
		m[0],  m[1],  m[2],  m[3],
		m[4],  m[5],  m[6],  m[7],
		m[8],  m[9],  m[10], m[11],
		m[12], m[13], m[14], m[15]
	);
}



void RendererDx::setProjOrtho( float* m )
{
	mDevice->SetTransform(D3DTS_PROJECTION, (D3DXMATRIXA16*) m );
	mProjection = glm::mat4(  
		m[0],  m[1],  m[2],  m[3],
		m[4],  m[5],  m[6],  m[7],
		m[8],  m[9],  m[10], m[11],
		m[12], m[13], m[14], m[15]
	);
}

void RendererDx::setLightType(int which, DEXGELLIGHTTYPE type)
{
	assert(which >= 0 && which < mMaxLights);

	mLights[which].Type = (D3DLIGHTTYPE)type;
}

// Sets the world position of "which" light
void RendererDx::setLightPos(int which, const glm::vec3 &pos)
{
	assert(which >= 0 && which < mMaxLights);

	mLights[which].Position.x = pos.x;
	mLights[which].Position.y = pos.y;
	mLights[which].Position.z = pos.z;
}

// Sets the direction "which" light is shinning
void RendererDx::setLightDir(int which, const glm::vec3 &dir)
{
	assert(which >= 0 && which < mMaxLights);

	mLights[which].Direction.x = dir.x;
	mLights[which].Direction.y = dir.y;
	mLights[which].Direction.z = dir.z;
}

// Sets "which" light three color values
// D3DLIGHT9 color values are between (0.0f, 1.0f)
void RendererDx::setLightColor(int which, int diffuse, int specular, int ambient)
{
	assert(which >= 0 && which < mMaxLights);

	mLights[which].Diffuse.a = GET_A(diffuse) / 255.0f;
	mLights[which].Diffuse.b = GET_B(diffuse) / 255.0f;
	mLights[which].Diffuse.g = GET_G(diffuse) / 255.0f;
	mLights[which].Diffuse.r = GET_R(diffuse) / 255.0f;

	mLights[which].Specular.a = GET_A(specular) / 255.0f;
	mLights[which].Specular.b = GET_B(specular) / 255.0f;
	mLights[which].Specular.g = GET_G(specular) / 255.0f;
	mLights[which].Specular.r = GET_R(specular) / 255.0f;

	mLights[which].Ambient.a = GET_A(ambient) / 255.0f;
	mLights[which].Ambient.b = GET_B(ambient) / 255.0f;
	mLights[which].Ambient.g = GET_G(ambient) / 255.0f;
	mLights[which].Ambient.r = GET_R(ambient) / 255.0f;
}

void RendererDx::setLightAttenuation(int which, float constant, float linear, float quad )
{
	assert(which >= 0 && which < mMaxLights);

	mLights[which].Attenuation0 = constant;
	mLights[which].Attenuation1 = linear;
	mLights[which].Attenuation2 = quad;
}

void RendererDx::setLightRange(int which, float r)
{
	assert(which >= 0 && which < mMaxLights);

	mLights[which].Range = r;
}

// Sets "which" light's inner and outer radius that define
// it's intensity.  "innerCone" is the angle in radians of where the full intensity of the
// light will hit.  It must in the range of (0.0f, outerCone).  "outerCone" is the angle
// in radians of the complete area the light will illuminate.  It must be in the
// range of (0.0f, PI) 
void RendererDx::setLightRadius(int which, float innerCone, float outerCone)
{
	assert(which >= 0 && which < mMaxLights);
	assert(innerCone >= 0.0f && innerCone <= outerCone);
	assert(outerCone >= 0.0f && outerCone <= D3DX_PI);	

	mLights[which].Theta = innerCone;
	mLights[which].Phi = outerCone;
}

// Sets the status (either on or off) of "which" light
void RendererDx::setLightActive(int which, bool onOrOff)
{
	assert(which >= 0 && which < mMaxLights);

	// Tell the device about the light 
	mResult = mDevice->SetLight(which, &mLights[which]);
	assert(mResult == D3D_OK);

	// Either turn it on or off
	mResult = mDevice->LightEnable(which, onOrOff);
	assert(mResult == D3D_OK);
}

bool RendererDx::initLights()
{
	D3DCAPS9 caps; // Struct to hold the device's capabilites

	// First we need to get the device's capabilites so we can determine
	// how many lights we can have
	if(mInterface->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps) != D3D_OK)
		return false;

	// Store the maximum number of lights
	mMaxLights = caps.MaxActiveLights;

	// Now we'll create an array of lights that is as big as 
	// the maximum number of lights we could possibly have
	mLights = new D3DLIGHT9[mMaxLights];

	// Error Check
	if(!mLights) return false;

	// Zero out the light structs
	ZeroMemory(mLights, sizeof(D3DLIGHT9) * mMaxLights);

	// Init each light struct to default values
	for(int i = 0; i < mMaxLights; ++i)
	{
		mLights[i].Type = D3DLIGHT_POINT;
		mLights[i].Attenuation1 = 1.0f;
		mLights[i].Attenuation2 = 0.0f;
		mLights[i].Falloff = 1.0f;
		mLights[i].Range = 500.0f;
		mLights[i].Diffuse.a = 1.0f; // Set diffuse color to solid white with full alpha
		mLights[i].Diffuse.b = 1.0f;
		mLights[i].Diffuse.g = 1.0f;
		mLights[i].Diffuse.r = 1.0f;
		mLights[i].Specular = mLights[i].Diffuse; // Specular is the same as diffuse color
		mLights[i].Phi = DEG2RAD(180);
		mLights[i].Theta = DEG2RAD(45);
		mLights[i].Direction = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
		mLights[i].Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	}

	// Finally, turn on some ambient light.
	mDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );
	//mDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(50,50,50) );

	return true; // Lights initialized properly
	
}

Texture* RendererDx::loadTexture( const std::string filename )
{
	Texture *t = new TextureDX();
	if (t->load(filename) )
	{
		return t;
	}
	return NULL;
}

Mesh* RendererDx::createMesh( SVertex* verts, int numVerts )
{
	Mesh *m = new MeshDx();
	if (m->setVertexData( verts, numVerts ) == false)
	{
		throw char("failed to create mesh...");
		return NULL;
	}
	return m;
}
Mesh* RendererDx::createMesh( LitVertex* verts, int numVerts )
{
	Mesh *m = new MeshDx();
	if (m->setVertexData( verts, numVerts ) == false)
	{
		throw char("failed to create mesh...");
		return NULL;
	}
	return m;
}

bool dexgel::priv::RendererDx::render( Mesh * mesh_base )
{
	MeshDx* meshDxPtr = reinterpret_cast<MeshDx*>( mesh_base );

	HRESULT result;

#ifndef SHADER_LIGHTING
	// Set the vertex data
	// By parameter:
	// 0 -- The stream number of the data.  D3D allows for multiple streams
	//		of data to be used in a particular render.  The streams use
	//		zero based counting and since we only have (which is typically the case)
	//		we pass zero
	// mVertexBuffer -- The IDirect3DVertexBuffer9* to use for rendering
	// 0 -- Offset in bytes, to the beginning of where to start rendering in
	//		the vertex buffer.  We want to begin rendering from the start of the 
	//		the vertex buffer so we pass zero
	// sizeof(SVertex) -- The size, in bytes, of an individual vertex stored 
	//					  in the vertex buffer

	int struct_bytes = 0;
	if (meshDxPtr->type_to_render == SVertexType ) 
	{
		struct_bytes = sizeof(SVertex);
	}else{
		struct_bytes = sizeof(LitVertex);
	}

	result = mDevice->SetStreamSource(0, meshDxPtr->mVertexBuffer, 0, struct_bytes );
	assert(result == D3D_OK);

	//Specify vertex type
	// SVertexType -- Is the #define which defines our vertex in "vertex_types.h"
	mDevice->SetFVF(meshDxPtr->type_to_render);

	// Draw the geometry
	// By paramater:
	// D3DPT_TRIANGLELIST -- The primitive to use when rendering the vertex buffer
	//						 Our mesh always assumes triangles
	// 0 -- The index of the first vertex to use when rendering.  We want
	//		to begin rendering with the first vertex, so we pass zero
	// mTriCount -- The number of triangles to render
	result = priv::RendererDx::mDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,meshDxPtr->mTriCount);
	assert(result == D3D_OK);

	return true;
#endif

#ifdef SHADER_LIGHTING
	int struct_bytes = 0;
	if (meshDxPtr->type_to_render == SVertexType ) 
	{
		struct_bytes = sizeof(SVertex);
	}else{
		struct_bytes = sizeof(LitVertex);
	}

	result = mDevice->SetStreamSource(0, meshDxPtr->mVertexBuffer, 0, struct_bytes );
	assert(result == D3D_OK);

	// Specify vertex type
	// SVertexType -- Is the #define which defines our vertex in "vertex_types.h"
	mDevice->SetFVF(meshDxPtr->type_to_render);


	const int MAX_LIGHTS = 1;
	glm::vec3 vLightDir[MAX_LIGHTS];
	glm::vec3 vLightDiffuse[MAX_LIGHTS];

	for( int i=0; i<MAX_LIGHTS; i++ )
	{
		vLightDir[i] = glm::vec3(0.0f, 1.0f, 0.0f);

		vLightDiffuse[i] = glm::vec3(1.0f, 1.0f, 1.0f);
	}
	
	int g_nNumActiveLights = 1;

	// shader 

#ifndef V
#define V(x)           { result = (x); assert(result == D3D_OK); }
#endif


	V( mEffect->SetMatrix( "gProjMat",  (D3DXMATRIX*) &mProjection[0] ) );
	V( mEffect->SetMatrix( "gViewMat",  (D3DXMATRIX*) &mWorldView[0] ) );
	V( mEffect->SetMatrix( "gWorldMat",  (D3DXMATRIX*) &mWorld[0] ) );

	V( mEffect->SetValue( "gLightPos", (D3DXVECTOR3*) &mLights[0].Position, sizeof( D3DXVECTOR3 ) * MAX_LIGHTS ) );

	D3DXCOLOR colorMtrlDiffuse( 1.0f, 1.0f, 1.0f, 1.0f );
	D3DXCOLOR colorMtrlSpecular( 0.95f, 0.95f, 0.95f, 1.0f );
	D3DXCOLOR colorMtrlAmbient( 0.35f, 0.35f, 0.35f, 1.0f );

	mEffect->SetValue( "gDiffuse", &colorMtrlDiffuse, sizeof( D3DXCOLOR ) );
	mEffect->SetValue( "gSpecular", &colorMtrlSpecular, sizeof( D3DXCOLOR ) );
	mEffect->SetValue( "gAmbient", &colorMtrlAmbient, sizeof( D3DXCOLOR ) );

	// Render the scene with this technique 
	// as defined in the .fx file
	
	//V( mEffect->SetTechnique( "VertexLighting" ) ); 
	V( mEffect->SetTechnique( "PerPixelLighting" ) ); 
	

	// Apply the technique contained in the effect 
	unsigned int cPasses = 0;
	V( mEffect->Begin( &cPasses, 0 ) );

	for( size_t iPass = 0; iPass < cPasses; iPass++ )
	{
		V( mEffect->BeginPass( iPass ) );

		// The effect interface queues up the changes and performs them 
		// with the CommitChanges call. You do not need to call CommitChanges if 
		// you are not setting any parameters between the BeginPass and EndPass.
		// V( mEffect->CommitChanges() );

		// Render the mesh with the applied technique
		result = mDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,meshDxPtr->mTriCount);
		assert(result == D3D_OK);

		V( mEffect->EndPass() );
	}
	V( mEffect->End() );
 #undef V
	return true;
#endif

	
}
